﻿using BeetleX;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Net;
namespace Athena.Transport.BeetleX
{
    using Codec;
    using Implementations;
    using Message;
    using Options;
    public class BeetleXTransportClientFactory : ITransportClientFactory, IDisposable
    {
        private readonly TransportOption _transportOption;
        private readonly IRpcMessageCodecFactory _rpcMessageCodecFactory;
        private readonly IRpcMessageEncoder _rpcMessageEncoder;
        private readonly IRpcMessageDecoder _rpcMessageDecoder;
        private readonly ILogger _logger;
        private readonly ConcurrentDictionary<EndPoint, Lazy<ITransportClient>> _clientDictionary;

        public BeetleXTransportClientFactory(TransportOption transportOption, IRpcMessageCodecFactory rpcMessageCodecFactory, ILogger<BeetleXTransportClientFactory> logger)
        {
            _transportOption = transportOption;
            _rpcMessageCodecFactory = rpcMessageCodecFactory;
            _rpcMessageEncoder = _rpcMessageCodecFactory.CreateEncoder();
            _rpcMessageDecoder = _rpcMessageCodecFactory.CreateDecoder();
            _logger = logger;
            _clientDictionary = new ConcurrentDictionary<EndPoint, Lazy<ITransportClient>>();
        }

        public ITransportClient CreateClient(EndPoint endPoint)
        {
            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogError($"开始创建客户端 通讯地址：{endPoint}");
            }

            return _clientDictionary.GetOrAdd(endPoint, x => new Lazy<ITransportClient>(() =>
            {
                var messageListenerLinker = new TransportMessageListener();
                var beetleXTransportMessageClientSender = new BeetleXTransportMessageClientSender(_rpcMessageEncoder, endPoint);
                beetleXTransportMessageClientSender.TcpClient.DataReceive = async (client, clientReceiveArgs) =>
                {
                    var rpcTransportMessage = _rpcMessageDecoder.MessageDecoding(clientReceiveArgs.Stream.ToPipeStream().ReadUTF());
                    await messageListenerLinker.OnReceived(
                   beetleXTransportMessageClientSender, rpcTransportMessage);
                };
                return new TransportClient(_transportOption, beetleXTransportMessageClientSender, messageListenerLinker, _logger);
            })).Value;
        }

        public void DestoryClient(EndPoint endPoint)
        {
            _clientDictionary.TryRemove(endPoint, out var value);
        }

        public void Dispose()
        {

        }
    }
}
